//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace Microsoft.Research.ScientificWorkflow.UIDesigner
{
    #region NameSpace
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Media;
    using Microsoft.Research.ScientificWorkflow.TridentModel;
    using System.ComponentModel;

    #endregion

    /// <summary>
    /// Interaction logic for AcctivityHeader.xaml
    /// </summary>
    public partial class ActivityHeader : UserControl, INotifyPropertyChanged
    {
        #region Declaration

        /// <summary>
        /// Holds the ActivityModel
        /// </summary>
        private BaseModel model;

        /// <summary>
        /// If valid mode or not.
        /// </summary>
        private bool updateAllowedMode;

        #endregion

        #region Events

        /// <summary>
        /// Event for Options Click.
        /// </summary>
        public event EventHandler OnOptionsClick;

        public event EventHandler<ModelEventArgs> UpdateClick;

        #endregion

        #region Constructor

        /// <summary>
        /// Constructor
       /// </summary>
        /// <param name="model">ActivityModel</param>
        /// <param name="activity">Activity</param>
        public ActivityHeader(BaseModel model)
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(this.OnLoaded);
            this.model = model;

            this.GenerateToolTip();
            this.DataContext = this.model;

            // If current instance is for preview, no need to display btnOption.
            if (model.IsPreview)
            {
                this.btnOptions.Visibility = Visibility.Hidden;
            }
        }

        #endregion
        
        #region Properties

        /// <summary>
        /// get and Set the Header Height
        /// </summary>
        public double HeaderHeight
        {
            get
            {
                return this.bdrActivityHeader.Height;
            }
            set
            {
                this.bdrActivityHeader.Height = value;
            }
        }

        /// <summary>
        /// get and Set the Header Width
        /// </summary>
        public double HeaderWidth
        {
            get
            {
                return this.bdrActivityHeader.Width;
            }
            set
            {
                this.bdrActivityHeader.Width = value;
            }
        }

        /// <summary>
        /// get and Set the Header Text
        /// </summary>
        public string HeaderText
        {
            get
            {
                return this.txtHeader.Text;
            }
            set
            {
                if (!string.IsNullOrEmpty(value))
                {
                    this.txtHeader.Text = value;
                }
                else
                {
                    value = string.Empty;
                }
            }
        }

        /// <summary>
        /// get and Set Header Background
        /// </summary>
        public Brush HeaderBackground
        {
            get
            {
                return this.bdrActivityHeader.Background;
            }
            set
            {
                this.bdrActivityHeader.Background = value;
            }
        }

        /// <summary>
        /// Gets a value indicating whether valid mode.
        /// </summary>
        /// <value><c>true</c> if valid mode; otherwise, <c>false</c>.</value>
        public bool UpdateAllowedMode
        {
            get
            {
                return this.updateAllowedMode;
            }

            set
            {
                this.updateAllowedMode = value;
                this.RaisePropertyChanged("UpdateAllowedMode");
            }
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Generates the Stack Panel with name and Description
        /// </summary>
        private void GenerateToolTip()
        {
            StackPanel toolTipStack = new StackPanel();
            DockPanel nameBlock = new DockPanel();
            TextBlock nameLabelBlock = new TextBlock();
            nameLabelBlock.Text = UIDesignerCodeConstants.ACTIVITYTOOLTIPNAME;
            nameLabelBlock.FontWeight = FontWeights.Bold;
            TextBlock nameTextBlock = new TextBlock();
            nameTextBlock.Text = this.model.Name;

            nameBlock.Children.Add(nameLabelBlock);
            nameBlock.Children.Add(nameTextBlock);

            DockPanel descriptionBlock = new DockPanel();
            TextBlock descriptionLabelBlock = new TextBlock();
            descriptionLabelBlock.Text = UIDesignerCodeConstants.ACTIVITYTOOLTIPDESCRIPTION;
            descriptionLabelBlock.FontWeight = FontWeights.Bold;
            TextBlock descriptionTextBlock = new TextBlock();
            descriptionTextBlock.Text = this.model.Description;

            descriptionBlock.Children.Add(descriptionLabelBlock);
            descriptionBlock.Children.Add(descriptionTextBlock);

            toolTipStack.Children.Add(nameBlock);
            toolTipStack.Children.Add(descriptionBlock);

            this.ToolTip = toolTipStack;
        }

        /// <summary>
        /// Fired on click of options button.
        /// </summary>
        /// <param name="sender">
        /// Options button.
        /// </param>
        /// <param name="e">
        /// RoutedEventArgs.
        /// </param>
        private void OnOptionsButtonClick(object sender, RoutedEventArgs e)
        {
            if (this.OnOptionsClick != null)
            {
                this.OnOptionsClick.Invoke(sender, e);
            }
        }

        /// <summary>
        /// Called when update click.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void OnUpdateClick(object sender, RoutedEventArgs e)
        {
            if (this.UpdateClick != null)
            {
                this.UpdateClick.Invoke(this, new ModelEventArgs(this.model));
            }
        }

        /// <summary>
        /// Fired on loaded.
        /// </summary>
        /// <param name="sender">This</param>
        /// <param name="e">RoutedEventArgs</param>
        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            string composerCtrlName = (string)this.GetValue(ComposerControl.ComposerControlNameProperty);
            ComposerControl composerCtrl = Application.Current.MainWindow.FindName(composerCtrlName) as ComposerControl;
            if (composerCtrl != null && composerCtrl.CurrentRenderMode == RenderMode.ComposerMode)
            {
                this.UpdateAllowedMode = true;
            }
        }

        #endregion

        #region INotifyPropertyChanged Members

        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Raises the property changed.
        /// </summary>
        /// <param name="name">The name.</param>
        protected void RaisePropertyChanged(string name)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }

        #endregion
    }

    public class ExecutionStatusImageConverter : IValueConverter
    {
        #region IValueConverter Members

        /// <summary>
        /// Get the image source and it's visibility based on the parameter passed.
        /// </summary>
        /// <param name="value">
        /// Value.
        /// </param>
        /// <param name="targetType">
        /// Targettype.
        /// </param>
        /// <param name="parameter">
        /// Parameter.
        /// </param>
        /// <param name="culture">
        /// Culture.
        /// </param>
        /// <returns>
        /// Binding value.
        /// </returns>
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            TridentActivityExecutionStatus status = (TridentActivityExecutionStatus)value;
            switch (parameter.ToString())
            {
                case "ExecStatusVisibility":
                    if (TridentActivityExecutionStatus.None == status)
                    {
                        return Visibility.Hidden;
                    }
                    else
                    {
                        return Visibility.Visible;
                    }

                case "ExecutingImageSource":
                    if (TridentActivityExecutionStatus.Executing == status)
                    {
                        return Visibility.Visible;
                    }
                    else
                    {
                        return Visibility.Hidden;
                    }

                case "CompletedImageSource":
                    if (TridentActivityExecutionStatus.Closed == status)
                    {
                        return Visibility.Visible;
                    }
                    else
                    {
                        return Visibility.Hidden;
                    }

                case "FaultingImageSource":
                    if (TridentActivityExecutionStatus.Faulting == status)
                    {
                        return Visibility.Visible;
                    }
                    else
                    {
                        return Visibility.Hidden;
                    }

                default:
                    return Visibility.Hidden;
            }
        }
        
        /// <summary>
        /// Not implemented.
        /// </summary>
        /// <param name="value"></param>
        /// <param name="targetType"></param>
        /// <param name="parameter"></param>
        /// <param name="culture"></param>
        /// <returns></returns>
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return value;
        }
        
        #endregion
    }

    public class UpdateVisibilityConverter : IMultiValueConverter
    {
        #region IMultiValueConverter Members

        /// <summary>
        /// Converts source values to a value for the binding target. The data binding engine calls this method when it propagates the values from source bindings to the binding target.
        /// </summary>
        /// <param name="values">The array of values that the source bindings in the <see cref="T:System.Windows.Data.MultiBinding"/> produces. The value <see cref="F:System.Windows.DependencyProperty.UnsetValue"/> indicates that the source binding has no value to provide for conversion.</param>
        /// <param name="targetType">The type of the binding target property.</param>
        /// <param name="parameter">The converter parameter to use.</param>
        /// <param name="culture">The culture to use in the converter.</param>
        /// <returns>
        /// A converted value.If the method returns null, the valid null value is used.A return value of <see cref="T:System.Windows.DependencyProperty"/>.<see cref="F:System.Windows.DependencyProperty.UnsetValue"/> indicates that the converter did not produce a value, and that the binding will use the <see cref="P:System.Windows.Data.BindingBase.FallbackValue"/> if it is available, or else will use the default value.A return value of <see cref="T:System.Windows.Data.Binding"/>.<see cref="F:System.Windows.Data.Binding.DoNothing"/> indicates that the binding does not transfer the value or use the <see cref="P:System.Windows.Data.BindingBase.FallbackValue"/> or the default value.
        /// </returns>
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            Visibility visibility = Visibility.Collapsed;

            // The first value will be whether the current mode is composer mode or not.
            // The second value will be whether update is available or not.
            if ((bool)values[0] && (bool)values[1])
            {
                visibility = Visibility.Visible;
            }

            return visibility;
        }

        /// <summary>
        /// Converts a binding target value to the source binding values.
        /// </summary>
        /// <param name="value">The value that the binding target produces.</param>
        /// <param name="targetTypes">The array of types to convert to. The array length indicates the number and types of values that are suggested for the method to return.</param>
        /// <param name="parameter">The converter parameter to use.</param>
        /// <param name="culture">The culture to use in the converter.</param>
        /// <returns>
        /// An array of values that have been converted from the target value back to the source values.
        /// </returns>
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }

        #endregion
    }
}
